'''在 Python 中，main_thread.daemon=True 这行代码通常用于将主线程设置为守护线程。
一、守护线程的概念
1.守护线程（Daemon Thread）是一种在后台运行的线程，它的作用是在非守护线程（通常是主线程和用户创建的其他重要线程）全部结束时自动退出，而不管守护线程是否还在运行。
二、具体解释
2.main_thread通常是指 Python 程序的主线程。设置 main_thread.daemon=True意味着当所有非守护线程（例如，用户创建的工作线程或者其他子线程，如果它们不是守护线程的话）结束时，主线程也会自动结束，即使此时主线程的任务还没有完成。
如果不设置为主守护线程（即main_thread.daemon=False，这是默认情况），那么主线程会一直运行，直到它自己的任务完成，即使其他非守护线程都已经结束。'''
'''在这段代码中，self.server = server的作用是将传入的服务器对象赋值给当前会话线程对象的server属性
这样做的好处是在会话线程中可以通过self.server来访问服务器对象的方法和属性，方便与服务器进行交互。例如，可以调用服务器的show_info_and_send_client方法来向所有客户端和服务器自身发送消息'''
'''import wx
from socket import socket,AF_INET,SOCK_STREAM
import threading
import time
class mwy_server(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,None,id=1002,title='mwy的服务器界面',pos=wx.DefaultPosition,size=(400,450))
        #窗口放一个面板
        pl=wx.Panel(self)
        #创建一个盒子
        box=wx.BoxSizer(wx.VERTICAL)#垂直放向上自动排版
        #可伸缩的网络布局
        fgz1=wx.FlexGridSizer(wx.HSCROLL)#水平方向布局

        start_server_btn=wx.Button(pl,size=(133,40),label='启动服务器')
        record_server_btn = wx.Button(pl, size=(133, 40), label='保留服务器')
        stop_server_btn = wx.Button(pl, size=(133, 40), label='停止服务器')
        #将三个按钮放入fgz1
        fgz1.Add(start_server_btn,1,wx.TOP)
        fgz1.Add(record_server_btn,1,wx.TOP)
        fgz1.Add(stop_server_btn,1,wx.TOP)
        #将可伸缩的网络布局放到box中
        box.Add(fgz1,1,wx.CENTER)
        #创建只读多行文本框
        self.show_text = wx.TextCtrl(pl, size=(400,410),style=wx.TE_MULTILINE | wx.TE_READONLY)  # wx.TE_MULTILINE表示多行文本框 wx.TE_READONLY表示只读
        box.Add(self.show_text, 1, wx.ALIGN_CENTRE)  # wx.ALIGN_CENTRE表示self.show_text添加入中间位置
        #将盒子放入电脑当中
        pl.SetSizer(box)
        '''--------------------以上代码都是界面绘制代码--------------------------'''
        '''服务器功能实现的必要性'''
        self.ison=False#存储服务器的启动状态 默认值位False 表示默认没有启动
        #服务器端绑定ip地址和端口号
        self.host_port=('',8888)#''是本机的所有ip地址
        #创建socket对象
        self.server_socket=socket(AF_INET,SOCK_STREAM)
        # #绑定IP地址和端口号
        self.server_socket.bind(self.host_port)
        #开始进行监听
        self.server_socket.listen(5)
        #创建一个字典:存储与客户端对话的线程
        self.session_thread_dict={}#key-value {客户端的名称key:会话线程value}

        #给启动服务绑定一个按钮
        self.Bind(wx.EVT_BUTTON,self.start_server,start_server_btn)#(绑定一个事件,编写一个方法,绑定一个按钮)
        #给保存聊天记录按钮绑定一个事件
        self.Bind(wx.EVT_BUTTON,self.save_record,record_server_btn)
        #给断开按钮绑定一个事件
        self.Bind(wx.EVT_BUTTON, self.stop_server,stop_server_btn)
    def stop_server(self):
        print('服务器停止服务')
        self.ison=False

    def save_record(self,event):
        record_data=self.show_text.GetValue()
        with open('record.log','w',encoding='utf-8') as file:
            file.write(record_data)

    def start_server(self,event):
        #判断服务器是否已经启动，只有服务器没有启动是才启动
        if not self.ison:
            #启动服务器
            self.ison=True
            #创建主线程，函数式创建主线程
            main_thread=threading.Thread(target=self.do_work)
            #设置为守护线程 父线程执行完毕（窗体界面） 子线程自动关闭
            main_thread.daemon=True
            #启动主线程
            main_thread.start()
    def do_work(self):
        #判断ison的值
        while self.ison:
            #接受客户端的连接请求
            session_socket,client_addr=self.server_socket.accept()
            #客户端发送连接请求之后，发送过来的第一条数据为客户端的名称，客户端的名称作为字典中的键
            user_name=session_socket.recv(1024).decode('utf-8')#clien_name(python_mwy)-->user_name
            #创建一个会话线程的对象(以类的方式创建)
            sesstion_thread=SesstionThread(session_socket,user_name,self)
            #存储到字典中
            self.session_thread_dict[user_name]=sesstion_thread
            #启动会话线程
            sesstion_thread.start()
            #输出服务器的提示信息
            self.show_info_and_send_client('服务器通知', f'{user_name}进入聊天室',time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))

            #当self.ison的值为False时，执行关闭socket对象
        self.server_socket.close()
    def show_info_and_send_client(self,data_source,data,datetime):
            send_data = f'{data_source}:{data}' + f'({datetime})'#data为客户端发送过来的数据(其中调用了SesstionThread(session_socket,user_name,self))
            #只读文本框
            self.show_text.AppendText('-'*40+'\n'+send_data+'\n')
            #每一个客户端发送一次
            for client in self.session_thread_dict.values():#遍历的每个值（value是socket对象）
                #如果当前的会话是否是开启状态
                if client.ison:
                    client.client_socket.send(send_data.encode('utf-8'))
                    #将客户端发送过来的数据发送给各个客户端


class SesstionThread(threading.Thread):
    def __init__(self,client_socket,user_name,server):
        #调用父类的初始化方法
        threading.Thread.__init__(self)
        self.client_socket=client_socket#client_socket这是一个自定义的参数，用于接收外部传递给构造方法的值。这个参数可以根据实际需求进行命名和定义不同的数据类型
        self.user_name=user_name
        self.server=server
        self.ison=True#会话线程是否启动，当创建SesstionThread对象时会话线程已经启动

    def run(self)->None:
        print(f'客户端：{self.user_name}已经和服务器连接成功,服务器启动一个会话线程')
        while self.ison:
            #从客户端接受数据 存储到data中
            data=self.client_socket.recv(1024).decode('utf-8')#接受数据解码
            #如果客户端点击断开按钮 先给服务器发送一句话 消息自定义 自定义的结束词
            if data=='mwy-disconnect':
                self.ison=False
                #进行发送服务器通知
                self.server.show_info_and_send_client('服务器通知',f'{self.user_name}离开聊天室',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))
            else:
                #其他聊天信息显示给所有的客户端 包含服务器也显示
                #调用
                self.server.show_info_and_send_client(self.user_name,data,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))
                #调用show_info_and_send_client()将data添加进show_text
        #关闭socket
        self.client_socket().close()'''








if __name__=='__main__':
        #创建一个app
        app=wx.App()
        #创建自己的服务器对象
        server=mwy_server()
        server.Show()
        #循环判断显示
        app.MainLoop()


